#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <juanmabc.h>
#include <GL/freeglut.h>
#include "jmbcPlayer.h"

unsigned int width, height, frame, ply, str, mdl[3], txs[2], action[2], tag, loop[2], font, img, ptl[2], mat;
float controller[3], ambient[4] = { 0.5f, 0.5f, 0.5f, 1.0f }, diffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f }, specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f }, position[4] = { 0.0f, 100.0f, 0.0f, 1.0f }, fog[4] = { 0.5f, 0.5f, 0.5f, 1.0f};
const float sum[16] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }, rest[16] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f, 1.0f }, gravity[16] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f };
float modelview[16], tmpmtx[16];
const wchar_t text[] = L"juanmabc engine ";

#define GLDEBUG \
{ \
	GLenum e; \
	while((e = glGetError()) != GL_NO_ERROR) \
	{ \
		fprintf(stderr, "%s:%i:%s\n", __FILE__, __LINE__, gluErrorString(e)); \
	} \
}

void
eglQuadX(float w, float h)
{
	float mw, mh;

	mw = w / 2.0f;
	mh = h / 2.0f;

	glPushMatrix();
	glMultMatrixf(tmpmtx);
	glBegin(GL_QUADS);
	glNormal3fv(mlVectorY);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(- mw, - mh, 0.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(mw, - mh, 0.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex3f(mw, mh, 0.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(- mw, mh, 0.0f);
	glEnd();
	glPopMatrix();
}

void
eglQuadY(float w, float h)
{
	float mw, mh;

	mw = w / 2.0f;
	mh = h / 2.0f;

	glPushMatrix();
	glMultMatrixf(tmpmtx);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(- mw, 0.0f, - mh);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(mw, 0.0f, - mh);
	glTexCoord2f(1.0f, 1.0f); glVertex3f(mw, 0.0f, mh);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(- mw, 0.0f, mh);
	glEnd();
	glPopMatrix();
}

void
eglQuadZ(float w, float h)
{
	float mw, mh;

	mw = w / 2.0f;
	mh = h / 2.0f;

	glPushMatrix();
	glMultMatrixf(tmpmtx);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, - mw, - mh);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(0.0f, mw, - mh);
	glTexCoord2f(1.0f, 1.0f); glVertex3f(0.0f, mw, mh);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, - mw, mh);
	glEnd();
	glPopMatrix();
}
void
jmbcBlowIn()
{
	srand((unsigned int) time(NULL));

	jmbcCreateContext();

	jmbcPlayerCreateContext();

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	glEnable(GL_TEXTURE_2D);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	//glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	//glEnable(GL_COLOR_MATERIAL);
	//glEnable(GL_POLYGON_SMOOTH);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_NORMALIZE);
//	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
//	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
//	glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
//	position[2] = -50.0f;
//	glLightfv(GL_LIGHT0, GL_POSITION, position);
	glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
//	position[2] = 0.0f;
	glLightfv(GL_LIGHT1, GL_POSITION, position);
//	glLightfv(GL_LIGHT2, GL_AMBIENT, ambient);
//	glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse);
//	glLightfv(GL_LIGHT2, GL_SPECULAR, specular);
//	position[2] = 50.0f;
//	glLightfv(GL_LIGHT2, GL_POSITION, position);

//	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	glEnable(GL_LIGHTING);
//	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHT1);
//	glEnable(GL_LIGHT2);
	glEnable(GL_FOG);
	glFogfv(GL_FOG_COLOR, fog);
	glFogi(GL_FOG_MODE, GL_LINEAR);
	glFogf(GL_FOG_START, 100.0f);
	glFogf(GL_FOG_END, 1000.0f);
	glFogf(GL_FOG_DENSITY, 0.15f);

	//glEnable(GL_ALPHA_TEST);
	//glAlphaFunc(GL_GREATER, 0.1f);

	//glEnable(GL_POINT_SMOOTH);
	//glPointSize(5.0f);

	glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
	glLoadIdentity();

	jmbcGenPlayers(1, &ply);

	tlGenStrings(1, &str);

	mlGenMeshes(1, &mdl[2]);
	tlStringLoad(str, PACKAGE_DATADIR L"/sky.cmesh");
	mlMeshLoad(mdl[2], str);
	tlStringUnload(str);

	mlGenModels(2, mdl);
	tlStringLoad(str, PACKAGE_DATADIR L"/robot.cmodel");
	mlModelLoad(mdl[0], str);
	tlStringUnload(str);
	tlStringLoad(str, PACKAGE_DATADIR L"/robot2.cmodel");
	mlModelLoad(mdl[1], str);
	tlStringUnload(str);

	mlGenMaterials(1, &mat);
	tlStringLoad(str, PACKAGE_DATADIR L"/power.cmaterial");
	mlMaterialLoad(mat, str);
	tlStringUnload(str);

	tlStringLoad(str, PACKAGE_DATADIR);
	mlModelGenMaterials(mdl[0], str);
	mlModelGenMaterials(mdl[1], str);
	mlMeshGenMaterials(mdl[2], str);
	mlMaterialGenTextures(mat, str);
	tlStringUnload(str);

	flGenFonts(1, &font);
	tlStringLoad(str, PACKAGE_DATADIR L"/VeraBd.ttf");
	flFontLoad(font, str);
	tlStringUnload(str);
	flFontSetPixelSizes(font, 16, 16);

	ilGenImages(1, &img);
	glGenTextures(2, txs);
	glBindTexture(GL_TEXTURE_2D, txs[0]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	tlStringLoad(str, PACKAGE_DATADIR L"/sky");
	ilImageLoad(img, str);
	ilImageTexImage2D(img);
	ilImageUnload(img);
	tlStringUnload(str);
	glBindTexture(GL_TEXTURE_2D, txs[1]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	tlStringLoad(str, PACKAGE_DATADIR L"/flake");
	ilImageLoad(img, str);
	ilImageTexImage2D(img);
	ilImageUnload(img);
	tlStringUnload(str);
	ilDeleteImages(1, &img);

	tlStringLoad(str, L"Walk");
	action[0] = mlModelAction(mdl[0], str);
	tlStringUnload(str);
	mlModelActionSet(mdl[0], action[0]);
	mlModelActionFrameSet(mdl[0], 0);
	tlStringLoad(str, L"Walk");
	action[1] = mlModelAction(mdl[1], str);
	tlStringUnload(str);
	mlModelActionSet(mdl[1], action[1]);
	mlModelActionFrameSet(mdl[1], 0);

	mlGenLoops(2, loop);
	mlLoopLoad(loop[0], 0.0f, (float) mlModelActionFrames(mdl[0], action[0]), 1.0f, 0.0f);
	mlLoopLoad(loop[1], 0.0f, (float) mlModelActionFrames(mdl[1], action[1]), 2.0f, 0.0f);

	tlStringLoad(str, L"Weapon");
	tag = mlModelTag(mdl[0], str);
	tlStringUnload(str);

	plGenParticles(2, ptl);
	plParticlesLoad(ptl[0], 500, 0);
	plParticlesAct(ptl[0], plParticlesActuatorInitializer, NULL);
	plParticlesLoad(ptl[1], 1000, 0);
	plParticlesAct(ptl[1], plParticlesActuatorInitializer, NULL);

	memset(controller, 0, 2 * sizeof(float));
	controller[2] = 1.0f;

	frame = 0;
}

void
jmbcBlowOut(void)
{
	mlMaterialDeleteTextures(mat);
	mlMaterialUnload(mat);
	mlDeleteMaterials(1, &mat);

	plParticlesUnload(ptl[1]);
	plParticlesUnload(ptl[0]);
	plDeleteParticles(2, ptl);

	tlDeleteStrings(1, &str);

	flFontUnload(font);
	flDeleteFonts(1, &font);

	mlDeleteLoops(2, loop);

	glDeleteTextures(2, txs);

	mlMeshDeleteMaterials(mdl[2]);
	mlMeshUnload(mdl[2]);
	mlDeleteMeshes(1, &mdl[2]);

	mlModelDeleteMaterials(mdl[0]);
	mlModelUnload(mdl[0]);
	mlModelDeleteMaterials(mdl[1]);
	mlModelUnload(mdl[1]);
	mlDeleteModels(2, mdl);

	jmbcDeletePlayers(1, &ply);

	jmbcDestroyContext();
}

void
jmbcReshape(int w, int h)
{
	width = w; height = h;
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (float) width / (float) height, 0.1f, 10000.0f);
	glMatrixMode(GL_MODELVIEW);
}
 
void
jmbcParticlesActuatorBall(unsigned int id, unsigned int particle, void *user)
{
	float *matrix;
	float *energy;

	matrix = plParticlesMatrix(id, particle);
	energy = plParticlesEnergy(id, particle);

	if((*energy) <= 0.0f)
	{
		float xr, yr, zr;
		*energy = 100.0f;
		mlMatrixLoadIdentity(matrix);
		xr = ((float) rand() / RAND_MAX - 0.5f) * 360.0f;
		yr = ((float) rand() / RAND_MAX - 0.5f) * 360.0f;
		zr = ((float) rand() / RAND_MAX - 0.5f) * 360.0f;
		mlMatrixRotate(matrix, mlVectorX, xr);
		mlMatrixRotate(matrix, mlVectorY, yr);
		mlMatrixRotate(matrix, mlVectorZ, zr);
		
	}
	else 
	{
		//if((*energy) >= 50.0f)
			mlMatrixMult(matrix, sum);
		//else
		//	mlMatrixMult(matrix, rest);
		(*energy) -= 5.0f;
	}
}

void
jmbcParticlesActuatorBallDraw(unsigned int id, unsigned int particle, void *user)
{
	float *matrix;

	matrix = plParticlesMatrix(id, particle);

	mlMatrixLoadBillboard(tmpmtx, modelview, &matrix[12]);

	eglQuadX(1.0f, 1.0f);
}

void
jmbcParticlesActuatorSnow(unsigned int id, unsigned int particle, void *user)
{
	float *matrix;
	float *energy;

	matrix = plParticlesMatrix(id, particle);
	energy = plParticlesEnergy(id, particle);

	if((*energy) <= 0.0f)
	{
		float xr, yr, zr;
		xr = ((float) rand() / RAND_MAX - 0.5f) * 300.0f;
		yr = ((float) rand() / RAND_MAX - 0.5f) * 50.0f + 50.0f;
		zr = ((float) rand() / RAND_MAX - 0.5f) * 300.0f;
		*energy = yr * 1.2f;
		mlMatrixLoad(matrix, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, xr, yr, zr, 1.0f);
		
	}
	else 
	{
		mlMatrixMult(matrix, gravity);
		(*energy) -= 1.0f;
	}
}

void
jmbcParticlesActuatorSnowDraw(unsigned int id, unsigned int particle, void *user)
{
	float *matrix;

	matrix = plParticlesMatrix(id, particle);

	mlMatrixLoadBillboard(tmpmtx, modelview, &matrix[12]);

	glPushMatrix();
	glMultMatrixf(tmpmtx);
	glBegin(GL_QUADS);
	glNormal3fv(mlVectorY);
	glTexCoord2f(0.0f, 0.0f); glVertex3i(-2, -2, 0);
	glTexCoord2f(1.0f, 0.0f); glVertex3i(2, -2, 0);
	glTexCoord2f(1.0f, 1.0f); glVertex3i(2, 2, 0);
	glTexCoord2f(0.0f, 1.0f); glVertex3i(-2, 2, 0);
	glEnd();
	glPopMatrix();
}

void
jmbcBlow(void)
{
	unsigned int i;
	wchar_t s[256], buffer[256];

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glLoadIdentity();

	jmbcPlayerControl(ply, controller);
	jmbcPlayerLook(ply);

	glLightfv(GL_LIGHT1, GL_POSITION, position);

	mlMaterialActionSet(mlMeshMaterialMaterial(mdl[2], 0), action[0] % 2);
	mlMaterialActionFrameSet(mlMeshMaterialMaterial(mdl[2], 0), frame % mlMaterialActionFrames(mlMeshMaterialMaterial(mdl[2], 0), action[0] % 2));
	mlMeshDraw(mdl[2]);

	mlMaterialActionSet(mat, action[0] % 2);
	mlMaterialActionFrameSet(mat, frame % mlMaterialActionFrames(mat, action[0] % 2));

	mlMaterialBind(mat);
	glMatrixMode(GL_TEXTURE);
	glPushMatrix();
	glMultMatrixf(mlMaterialMatrix(mat));
	glMatrixMode(GL_MODELVIEW);
	glBegin(GL_QUADS);
	glNormal3f(0.0f, 1.0f, 0.0f);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, -15.0f, 250.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(250.0f, -15.0f, 250.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex3f(250.0f, -15.0f, -250.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, -15.0f, -250.0f);
	glEnd();
	glMatrixMode(GL_TEXTURE);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);

	mlMaterialActionSet(mlModelMaterialMaterial(mdl[0], 0), action[0] % 2);
	mlMaterialActionFrameSet(mlModelMaterialMaterial(mdl[0], 0), frame % mlMaterialActionFrames(mlModelMaterialMaterial(mdl[0], 0), action[0] % 2));

	glPushMatrix();
	glRotatef(-90, 1.0f, 0.0f, 0.0f);
	for(i = 0; i < 6; i++)
	{
		mlModelDraw(mdl[0]);
		glPushMatrix();
		mlModelTagMatrix(mdl[0], tag, tmpmtx);
		glMultMatrixf(tmpmtx);
		mlModelDraw(mdl[1]);
		glPopMatrix();
		glTranslatef(20.0f, 0.0f, 0.0f);
	}
	for(i = 0; i < 6; i++)
	{
		mlModelDraw(mdl[1]);
		glPushMatrix();
		mlModelTagMatrix(mdl[1], tag, tmpmtx);
		glMultMatrixf(tmpmtx);
		mlModelDraw(mdl[0]);
		glPopMatrix();
		glTranslatef(20.0f, 0.0f, 0.0f);
	}
	glPopMatrix();

	mlLoopInc(loop[0]);
	mlModelActionFrameSet(mdl[0], (unsigned int) mlLoopValue(loop[0]));

	mlLoopInc(loop[1]);
	mlModelActionFrameSet(mdl[1], (unsigned int) mlLoopValue(loop[1]));

	//glDisable(GL_CULL_FACE);
        glEnable(GL_TEXTURE_GEN_S);
        glEnable(GL_TEXTURE_GEN_T);
	glMatrixMode(GL_TEXTURE);
	glPushMatrix();
	glScalef(0.1f, 0.1f, 0.1f);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(0.0f, 25.0f, 0.0f);
	for(i = 0; i < wcslen(text); i++)
		buffer[i] = text[(i + (unsigned int) (frame / 4.0f)) % wcslen(text)];
	buffer[i] = L'\0';
	swprintf(s, 256, L"<%02i>: %ls", (unsigned int) mlLoopValue(loop[0]), buffer);
	tlStringLoad(str, s);
	{
		float ambient[4] =
		{
			0.5, 0.5f, 0.5f, 1.0f
		};
		float diffuse[4] =
		{
			1.0, 1.0f, 1.0f, 1.0f
		};
		float specular[4] =
		{
			1.0, 1.0f, 1.0f, 1.0f
		};
		float emission[4] =
		{
			0.0, 0.0f, 0.0f, 1.0f
		};

		glBindTexture(GL_TEXTURE_2D, txs[0]);
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
		glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission);
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
	}
	flFontDrawStringSolid(font, str, 1);
	tlStringUnload(str);
	glPopMatrix();
	glMatrixMode(GL_TEXTURE);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
        glDisable(GL_TEXTURE_GEN_S);
        glDisable(GL_TEXTURE_GEN_T);
	//glEnable(GL_CULL_FACE);

	glDepthMask(GL_FALSE);
	plParticlesAct(ptl[0], jmbcParticlesActuatorSnow, NULL);
//	plParticlesDepthSort(ptl[0]);
	plParticlesAct(ptl[1], jmbcParticlesActuatorBall, NULL);
//	plParticlesDepthSort(ptl[1]);
	{
		float ambient[4] =
		{
			1.0, 1.0f, 1.0f, 1.0f
		};
		float diffuse[4] =
		{
			1.0, 1.0f, 1.0f, 1.0f
		};
		float specular[4] =
		{
			1.0, 1.0f, 1.0f, 1.0f
		};
		float emission[4] =
		{
			0.0, 0.0f, 0.0f, 1.0f
		};

		glBindTexture(GL_TEXTURE_2D, txs[1]);
		glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
		glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
		glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
		glMaterialfv(GL_FRONT, GL_EMISSION, emission);
		glMaterialf(GL_FRONT, GL_SHININESS, 100.0f);
	}
	glPushMatrix();
	glTranslatef(110.0f, 0.0f, 0.0f);
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
	plParticlesAct(ptl[1], jmbcParticlesActuatorBallDraw, NULL);
	plParticlesAct(ptl[0], jmbcParticlesActuatorSnowDraw, NULL);
	glPopMatrix();
	glDepthMask(GL_TRUE);

	GLDEBUG;

	glutSwapBuffers();

	frame++;
}

void
jmbcKeyboard(unsigned char key, int x, int y)
{
	if(key == 32) controller[2] = 4.0f;
}

void
jmbcKeyboardUp(unsigned char key, int x, int y)
{
	if(key == 32) controller[2] = 1.0f;
	if(key == 27) glutLeaveMainLoop();
}

void
jmbcSpecial(int key, int x, int y)
{
	switch(key)
	{
		case GLUT_KEY_UP: controller[1] = 1.0f; break;
		case GLUT_KEY_DOWN: controller[1] = -1.0f; break;
		case GLUT_KEY_LEFT: controller[0] = 1.0f; break;
		case GLUT_KEY_RIGHT: controller[0] = -1.0f; break;
	}
}

void
jmbcSpecialUp(int key, int x, int y)
{
	switch(key)
	{
		case GLUT_KEY_UP: controller[1] = 0.0f; break;
		case GLUT_KEY_DOWN: controller[1] = 0.0f; break;
		case GLUT_KEY_LEFT: controller[0] = 0.0f; break;
		case GLUT_KEY_RIGHT: controller[0] = 0.0f; break;
	}
}

void
jmbcMouseButton(int button, int state, int x, int y)
{
	switch(button)
	{
		case GLUT_LEFT_BUTTON:
			controller[1] = (float) (state == GLUT_DOWN) * 0.5f;
		break;
		case GLUT_RIGHT_BUTTON:
			if(state == GLUT_DOWN)
			{
				action[0] = (action[0] + 1) % mlModelActions(mdl[0]);
				mlModelActionSet(mdl[0], action[0]);
				mlModelActionFrameSet(mdl[0], 0);
				mlLoopLoad(loop[0], 0.0f, (float) mlModelActionFrames(mdl[0], action[0]), 1.0f, 0.0f);
				action[1] = (action[1] + 1) % mlModelActions(mdl[1]);
				mlModelActionSet(mdl[1], action[1]);
				mlModelActionFrameSet(mdl[1], 0);
				mlLoopLoad(loop[1], 0.0f, (float) mlModelActionFrames(mdl[1], action[1]), 2.0f, 0.0f);
			}
		break;
	}
}

void
jmbcMouseMotion(int x, int y)
{
	jmbcPlayerMotion(ply, (float) - (x - (int) width / 2) / 10.0f, (float) (y - (int) height / 2) / 10.0f);
}

void
jmbcTimer(int value)
{
	glutPostRedisplay();
	glutWarpPointer(width / 2, height / 2);
	glutTimerFunc(40, jmbcTimer, 0);
}

int
main(int argc, char **argv)
{
	int tmpargc = 1; 
	char *tmpargv[] = { "Demo", NULL };

	glutInit(&tmpargc, tmpargv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);

	width = glutGet(GLUT_SCREEN_WIDTH) * 3 / 4; height = glutGet(GLUT_SCREEN_HEIGHT) * 3 / 4;

	glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH) - width) / 2, (glutGet(GLUT_SCREEN_HEIGHT) - height) / 2);
	glutInitWindowSize(width, height);

	glutCreateWindow(tmpargv[0]);

	if(argc == 2 && !strcmp(argv[1], "--fullscreen"))
		glutFullScreen();

	glutWarpPointer(width / 2, height / 2);
	glutSetCursor(GLUT_CURSOR_NONE);


	glutDisplayFunc(jmbcBlow);
	glutReshapeFunc(jmbcReshape);
	glutKeyboardFunc(jmbcKeyboard);
	glutKeyboardUpFunc(jmbcKeyboardUp);
	glutSpecialFunc(jmbcSpecial);
	glutSpecialUpFunc(jmbcSpecialUp);
	glutMouseFunc(jmbcMouseButton);
	glutPassiveMotionFunc(jmbcMouseMotion);
	glutTimerFunc(20, jmbcTimer, 0);

	jmbcBlowIn();
	atexit(jmbcBlowOut);

	glutMainLoop();

	return EXIT_SUCCESS;
}
